package com.crm.service.crm.clue.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.crm.common.utils.POIUtilsLuoCheng;
import com.crm.model.common.dtos.PageResult;
import com.crm.model.common.dtos.PageResultSearch;
import com.crm.model.common.dtos.ResponseResult;
import com.crm.model.crm.clue.dtos.ClueDto;
import com.crm.model.crm.clue.dtos.ClueSearchDto;
import com.crm.model.crm.clue.pojos.Clue;
import com.crm.model.crm.clue.pojos.ClueCache;
import com.crm.model.crm.clue.vos.ClueVo;
import com.crm.model.crm.clue.vos.CueingResultVO;
import com.crm.service.crm.clue.mapper.ClueCheMapper;
import com.crm.service.crm.clue.mapper.ClueSMapper;
import com.crm.service.crm.clue.service.ClueSService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ClueSServiceImpl implements ClueSService {

    public static final byte UNCUED_POOL = 1;

    private static final String DERIVED_CLUE_TEMPLATE = "线索模板"; //表名

    private static final String CHECK_RESULT_DOWNLOAD = "校验结果下载";

    // 测试写死数据
    Long userId = 2l; // 从线程中获取身份id todo:暂未实现
    String userName = "张三"; //拥有人姓名

    @Autowired
    private ClueSMapper clueMapper;

    @Autowired
    private ClueCheMapper clueCheMapper;

    /**
     * 下载线索模板
     *
     * @param response
     * @return
     */
    @Override
    public ResponseResult template(HttpServletResponse response) {
        //  分页名
        List<String> tableSheetList = new ArrayList<>();
        tableSheetList.add("cell");

        // 创建模板的集合
        List<List<String>> tableData = new ArrayList<>();
        // 创建表字段名
        List<String> cell = new ArrayList<>();
        // 存入表字段
        String[] fields = {"手机号", "渠道来源", "活动信息", "客户姓名", "性别", "年龄", "微信", "QQ"};
        Collections.addAll(cell, fields);
        tableData.add(cell);

        // 导出为表格
        POIUtilsLuoCheng.exportTable(tableData, response, ClueSServiceImpl.DERIVED_CLUE_TEMPLATE, tableSheetList);

        return new ResponseResult(); //todo:响应部分的更改
    }

    /**
     * 线索页默认查询与条件查询
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult search(ClueSearchDto dto) {

        // 分页效验     如果为空返回默认 0 页    10 条
        dto.pageAndPageSizeNotNull();

        // 分页部分                         当前页         分页条数
        IPage<Clue> page = new Page<>(dto.getPage(), dto.getPageSize());

        // 动态条件
        LambdaQueryWrapper<Clue> lqe = new LambdaQueryWrapper<>();

        // 动态条件：手机号 | 线索id名字 | 线索归属 | 创建时间 | 线索状态 | 渠道来源
        lqe.like(dto.getPhoneNumber() != null, Clue::getPhoneNumber, dto.getPhoneNumber())
                .like(dto.getClueIdName() != null, Clue::getCueIdName, dto.getClueIdName() )
                .like(dto.getCluBelongerName() != null, Clue::getCueBelongerName,  dto.getCluBelongerName() )
                //todo: 时间部分没有测试
                .between(dto.getCreateTimeSrting() != null, Clue::getCreateTime, dto.getStarOfDay(), dto.getEndOfDay())
                .eq(dto.getCueStatus() != null, Clue::getCueStatus, dto.getCueStatus())
                .eq(dto.getChannelSource() != null, Clue::getChannelSource, dto.getChannelSource());
        // 查询拥有人id; todo:目前查询当前拥有人还未写出
        // 查询拥有人id + 登录用户id | 登录人 id + 登录人下属 id
        List<Long> ids = new ArrayList<>();
        ids.add(userId); // 写死部分的测试 id 添加集合
        lqe.in(Clue::getOwnerId, ids);
        lqe.eq(Clue::getCuePoolStatus, ClueSServiceImpl.UNCUED_POOL); //代表：非线索池  Todo:该常量需要归类

        // 分页查询
        clueMapper.selectPage(page, lqe);
        // 查询返回数据   原始数据 | Vo数据
        List<Clue> records = page.getRecords(); // 原始数据
        List<ClueVo> vos = new ArrayList<>();
        for (Clue record : records) {
            ClueVo clueVo = ClueVo.builder()
                    .clueIdName(record.getCueIdName())
                    .phoneNumber(record.getPhoneNumber())
                    .channelSource(record.getChannelSource())
                    .createDate(record.getCreateTime())
                    .cueBelongerName(record.getCueBelongerName())
                    .cueStatus(record.getCueStatus())
                    .operationStatus(record.getOperationStatus())
                    .build();
            vos.add(clueVo);
        }
        // 获取归属人的动态查询
        List<String> collect = records.stream().map(Clue::getCueBelongerName).distinct().collect(Collectors.toList());

        // 分页返回值                            当前数据    总条数
        PageResultSearch pageResultSearch = new PageResultSearch(page.getTotal(),vos,collect);

        // 将分页返回
        return ResponseResult.okResult(pageResultSearch);
    }

    /**
     * 上传线索表
     *
     * @param clueTable
     * @return
     */
    @Override
    public ResponseResult importClueTabel(MultipartFile clueTable) {

        // 准备解析实体类的数据
        List<List<String>> dataLists = null; // 解析的表获取的 DataList 集合

        try {
            dataLists = POIUtilsLuoCheng.parseExcel(clueTable);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (dataLists == null || dataLists.size() == 0) {
            throw new RuntimeException("数据为空"); // todo:改成常量类型
        }

        // 获取 ClueChe 集合
        List<ClueCache> listEntity = parsingListToEntity(dataLists);

        // 将 ClueChe 放入Clue缓存表中
        for (ClueCache clueCache : listEntity) {
            clueCheMapper.insert(clueCache);
        }
        return null;
    }

    /**
     * 删除上传的表   线索缓存表
     *
     * @return
     */
    @Override
    public ResponseResult uploadClueDelete() {
        clueCheMapper.delete(new LambdaQueryWrapper<ClueCache>().eq(ClueCache::getUserId, userId));
        return new ResponseResult();
    }

    /**
     * 效验批量上传线索结果
     *
     * @return
     */
    @Override
    public ResponseResult verificationClueResult() {
        List<ClueCache> clueCaches = clueCheMapper // 获取缓存线索表的数据
                .selectList(new LambdaQueryWrapper<ClueCache>().eq(ClueCache::getUserId, userId));

        Set<String> uniquePhoneNumbers = new HashSet<>(); // 用于存储唯一的手机号码
        long duplicateCount = clueCaches.stream() // 获取重复数
                .map(ClueCache::getPhoneNumber) // 只保留手机号信息
                .filter(phoneNumber -> !uniquePhoneNumbers.add(phoneNumber)) // 判断是否为重复手机号
                .count(); // 统计

        long sum = clueCaches.size(); //总条数
        long saveCount = sum - duplicateCount; // 可成功导入数

        CueingResultVO cueingResultVO = CueingResultVO.builder()
                .repeatingDataNumber(duplicateCount)
                .systemImportNumber(sum)
                .successfulImportNumber(saveCount)
                .build();

        return ResponseResult.okResult(cueingResultVO);
    }

    /**
     * 保存批量上传的线索
     *
     * @return
     */
    @Override
    public ResponseResult clueBatchSave() {

        List<ClueCache> clueCaches = clueCheMapper // 获取缓存线索表的数据
                .selectList(new LambdaQueryWrapper<ClueCache>().eq(ClueCache::getUserId, userId));

        Set<String> uniquePhoneNumbers = new HashSet<>(); // 用于存储唯一的手机号码
        List<ClueCache> distinctClueCaches = clueCaches.stream()
                .filter(clue -> uniquePhoneNumbers.add(clue.getPhoneNumber()))
                .collect(Collectors.toList());

        List<Clue> clues = new ArrayList<>();
        for (ClueCache distinctClueCach : distinctClueCaches) {
            Clue clue = new Clue();
            BeanUtils.copyProperties(distinctClueCach, clue);
            // 生成六位随机数代码 todo:常量
            String s = generateRandomNumber(6);
            String clueIdName = "XS" + s;
            clue.setCueIdName(clueIdName);
            // 相关状态 线索状态 | 是否是伪线索 | 所属人id | 操作状态 todo:常量
            clue.setCueStatus((byte) 0); // 0 待跟进
            clue.setCuePoolStatus((byte) 1); // 1 非伪线索
            clue.setCueBelongerId(userId); // 所属人 id
            clue.setCueBelongerName(userName); // 所属人姓名
            clue.setOperationStatus((byte) 1); //分配状态
            clue.setCreateTime(LocalDateTime.now()); // 创建时间
            clue.setOwnerId(userId);
            // 添加进 clues 集合
            clues.add(clue);
        }

        // 保存进线索表
        for (Clue clue : clues) {
            clueMapper.insert(clue);
        }

        // 删除掉原有的线索缓存表
        clueCheMapper.delete(new LambdaQueryWrapper<ClueCache>().eq(ClueCache::getUserId, userId));
        return new ResponseResult();
    }

    /**
     * 下载效验结果表
     *
     * @param dto
     * @param response
     * @return
     */
    @Override
    public ResponseResult checkResultDownload(CueingResultVO dto, HttpServletResponse response) {

        if (dto == null) {
            throw new RuntimeException("数据不存在");
        }

        //  分页名
        List<String> tableSheetList = new ArrayList<>();
        tableSheetList.add("cell");

        // 创建模板的集合
        List<List<String>> tableData = new ArrayList<>();

        // 创建数据表
        List<String> cellList = new ArrayList<>();
        // 存入表字段
        String[] fields = {"系统导入数", "导入重复数", "可成功导入数"};
        Collections.addAll(cellList, fields);
        tableData.add(cellList);

        // 存入数据
        List<String> dataList = new ArrayList<>();
        String[] datas = {dto.getSystemImportNumber().toString()
                , dto.getRepeatingDataNumber().toString()
                , dto.getSuccessfulImportNumber().toString()};
        Collections.addAll(dataList, datas);
        tableData.add(dataList);

        // 导出为表格
        POIUtilsLuoCheng.exportTable(tableData, response, ClueSServiceImpl.CHECK_RESULT_DOWNLOAD, tableSheetList);

        return new ResponseResult();
    }

    /**
     * 新建线索
     * @param dto todo:需要补充参数效验
     * @return
     */
    @Override
    public ResponseResult saveNewClue(ClueDto dto) {

        Clue clue = new Clue();
        BeanUtils.copyProperties(dto,clue);
        // 生成六位随机数代码
        String s = generateRandomNumber(6);
        String clueIdName = "XS" + s;
        clue.setCueIdName(clueIdName);
        // 相关状态 线索状态 | 是否是伪线索 | 拥有人id | 操作状态 todo:常量
        clue.setCueStatus((byte) 0); // 0 待跟进
        clue.setCuePoolStatus((byte) 1); // 1 非伪线索
        clue.setCueBelongerId(userId); // 所属人 id
        clue.setOperationStatus((byte) 1); // 未分配
        clue.setCueBelongerName(userName); // 所属人姓名
        clue.setOwnerId(userId); //todo:暂时写死的拥有人 id
        clue.setCreateTime(LocalDateTime.now()); //创建时间

        clueMapper.insert(clue);
        return new ResponseResult();
    }

    /**
     * 回显部门
     * @return
     */
    @Override
    public ResponseResult findAllDepartment() {

        return null;
    }

    /**
     * 将表解析的集合放入对应实体类集合当中； todo:该部分可能需要补充数据效验部分,数据结果验证只考虑去重问题；
     *
     * @param tableData
     * @return
     */
    private List<ClueCache> parsingListToEntity(List<List<String>> tableData) {
        // 收集实体类集合
        List<ClueCache> clueCachesList = new ArrayList<>();

        // index 去掉表头部分 | 获取数据行 ： 跟实体类是对齐关系
        for (int index = 1; index < tableData.size(); index++) {
            List<String> list = tableData.get(index);
            ClueCache clueCache = ClueCache.builder()
                    .phoneNumber(list.get(0))
                    .channelSource(Byte.parseByte(list.get(1)))
                    .activityInformation(Byte.parseByte(list.get(2)))
                    .customerName(list.get(3))
                    .gender(Byte.parseByte(list.get(4)))
                    .age(Byte.parseByte(list.get(5)))
                    .weChat(list.get(6))
                    .qq(list.get(7))
                    .userId(userId)
                    .build();
            // 增加实体类
            clueCachesList.add(clueCache);
        }
        return clueCachesList;
    }

    /**
     * 6位生成随机数
     *
     * @param length
     */
    private String generateRandomNumber(int length) {
        Random random = new Random();
        String sb = "";

        for (int i = 0; i < length; i++) {
            int digit = random.nextInt(10); // 生成 0-9 的随机数字
            sb += digit;
        }
        return sb;
    }

}
